﻿using Furion;
using Furion.DatabaseAccessor;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Furion.UnifyResult;
using JoyAdmin.Core;
using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Serilog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using TulingMember.Application.Dto;
using TulingMember.Application.Util;
using TulingMember.Application.ViewModel;
using TulingMember.Core;
using Yitter.IdGenerator;
using System.IO;
using static SKIT.FlurlHttpClient.Wechat.TenpayV3.Models.QueryMarketingMemberCardOpenCardsResponse.Types.Card.Types;
using TulingMember.Application.Helper;

namespace TulingMember.Application
{
    public class CustomerService : IDynamicApiController
    {
        private readonly ILogger _logger;
        private readonly IRepository<cts_Customer> _customerRepository;
        private readonly IRepository<cts_Department> _departmentRepository;
        private readonly IRepository<cts_CustomerPayLog> _customerpaylogRepository;
        private readonly IRepository<cts_SaleOrder> _saleorderRepository;
        public CustomerService(ILogger logger
            , IRepository<cts_Customer> customerRepository, IRepository<cts_Department> departmentRepository
            , IRepository<cts_CustomerPayLog> customerpaylogRepository
            , IRepository<cts_SaleOrder> saleorderRepository)
        {
            _logger = logger;
            _customerRepository = customerRepository;
            _departmentRepository = departmentRepository;
            _customerpaylogRepository = customerpaylogRepository;
            _saleorderRepository = saleorderRepository;
        }
        private static int Balance = App.GetConfig<int>("Common:Balance");
        #region 客户管理
        /// <summary>
        /// 客户统计
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public PagedList<CustomerDto> CustomerStatistics(BaseInput input)
        {
            var search = _customerRepository.Include(s => s.Department)
                .Include(s => s.SaleOrders)
                .AsQueryable();
            if (!string.IsNullOrEmpty(input.keyword))
            {
                search = search.Where(m => m.Name.Contains(input.keyword)
                || m.MedicalCardNo.Contains(input.keyword));
            }
            if (input.sdate != null)
            {
                search = search.Where(m => m.CreatedTime >= input.sdate);
            }
            if (input.edate != null)
            {
                var edate = input.edate?.AddDays(1).Date;
                search = search.Where(m => m.CreatedTime < edate);
            }
            if (input.typeid > 0)
            {
                var typeIds = _departmentRepository.Where(m => m.ParentIds.Contains(input.typeid.ToString())).Select(m => m.Id).ToList();
                typeIds.Add(input.typeid);
                search = search.Where(m => typeIds.Contains(m.DepartmentId));
            }

            var data = search.ToPagedList(input.page, input.size);

            var result = new PagedList<CustomerDto>
            {
                PageIndex = data.PageIndex,
                PageSize = data.PageSize,
                TotalCount = data.TotalCount,
                TotalPages = data.TotalPages,
                HasNextPages = data.HasNextPages,
                HasPrevPages = data.HasPrevPages
            };

            result.Items = data.Items.Select(s => new CustomerDto
            {
                Id = s.Id,
                Name = s.Name,
                Phone = s.Phone,
                Balance = s.Balance,
                //Birthday = s.Birthday,
                MedicalCardNo = s.MedicalCardNo,
                Sex = Convert.ToInt32(s.Sex),
                DepartmentId = s.DepartmentId,
                DepartmentName = s.Department.Name,
                ConsumptionAmount = s.SaleOrders.Sum(m => m.Amount),
                visits = s.SaleOrders.Count
            });

            return result;
        }
        /// <summary>
        /// 重置余额
        /// </summary>
        [UnitOfWork]
        public async Task ResetCustomerBalance()
        {
            var searchsaleorder = _saleorderRepository.Where(x => x.Status != 1).AsQueryable();
            if (searchsaleorder.Count() > 0)
            {
                throw Oops.Bah("存在未审批的处方单不能重置余额,请检查").StatusCode(ErrorStatus.ValidationFaild);
            }
            List<cts_Customer> customer = _customerRepository.Where(m => !m.IsDeleted).ToList();
            List<cts_CustomerPayLog> customerPayLogList = new List<cts_CustomerPayLog>();
            foreach (cts_Customer cus in customer)
            {
                cts_CustomerPayLog cts_CustomerPayLog = new cts_CustomerPayLog();
                cts_CustomerPayLog.Id = YitIdHelper.NextId();
                cts_CustomerPayLog.CustomerId = cus.Id;
                cts_CustomerPayLog.CustomerName = cus.Name;
                cts_CustomerPayLog.ChangeAmount = Balance - cus.Balance;
                cts_CustomerPayLog.OldAmount = cus.Balance;
                cts_CustomerPayLog.NewAmount = Balance;
                cts_CustomerPayLog.OrderDate = DateTime.Now.Date;
                cts_CustomerPayLog.Remark = "账目重置";
                cus.Balance = Balance;
                customerPayLogList.Add(cts_CustomerPayLog);
            }
            await _customerpaylogRepository.InsertAsync(customerPayLogList);
            await _customerRepository.UpdateAsync(customer);
        }
        /// <summary>
        /// 客户统计-导出
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<IActionResult> ExportCustomerStatistics([FromQuery] BaseInput input)
        {
            List<CustomerExport> data = this.GetExportCustomerData(input);
            var fileStream = ExcelHelper.ParseListToExcel(data);
            var fileName = HttpUtility.UrlEncode("人员统计_" + DateTime.Now.ToString("yyyyMMddhhmmss") + ".xlsx", Encoding.GetEncoding("UTF-8"));
            return await Task.FromResult(
             new FileContentResult(fileStream.ToArray(), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
             {
                 FileDownloadName = fileName
             });
        }

        private List<CustomerExport> GetExportCustomerData(BaseInput input)
        {
            List<CustomerExport> data = new List<CustomerExport>();
            var search = _customerRepository.Include(s => s.Department)
                 .Include(s => s.SaleOrders)
                 .AsQueryable();
            if (!string.IsNullOrEmpty(input.keyword))
            {
                search = search.Where(m => m.Name.Contains(input.keyword)
                || m.MedicalCardNo.Contains(input.keyword));
            }
            if (input.sdate != null)
            {
                search = search.Where(m => m.CreatedTime >= input.sdate);
            }
            if (input.edate != null)
            {
                var edate = input.edate?.AddDays(1).Date;
                search = search.Where(m => m.CreatedTime < edate);
            }
            if (input.typeid > 0)
            {
                var typeIds = _departmentRepository.Where(m => m.ParentIds.Contains(input.typeid.ToString())).Select(m => m.Id).ToList();
                typeIds.Add(input.typeid);
                search = search.Where(m => typeIds.Contains(m.DepartmentId));
            }
            data = search.Select(s => new CustomerExport
            {
                Name = DisPlayNameHelper.GetDisplayName(s.Name),
                //Phone = s.Phone,
                //Address = s.Address,
                Remark = s.Remark,
                Balance = s.Balance,
                //Birthday = s.Birthday,
                MedicalCardNo = s.MedicalCardNo,
                SexText = DescriptionExtension.GetEnumDescription(s.Sex),
                DepartmentName = s.Department.Name,
                ConsumptionAmount = s.SaleOrders.Sum(m => m.Amount),
                visits = s.SaleOrders.Count
            }).ToList();
            return data;
        }

        /// <summary>
        /// 列表
        /// </summary> 
        public PagedList<CustomerDto> SearchCustomer(BaseInput input)
        {
            var search = _customerRepository.AsQueryable();
            if (!string.IsNullOrEmpty(input.keyword))
            {
                search = search.Where(m => m.Name.Contains(input.keyword)
                || m.MedicalCardNo.Contains(input.keyword));
            }
            if (input.typeid > 0)
            {
                var typeIds = _departmentRepository.Where(m => m.ParentIds.Contains(input.typeid.ToString())).Select(m => m.Id).ToList();
                typeIds.Add(input.typeid);
                search = search.Where(m => typeIds.Contains(m.DepartmentId));
            }
            var amount = search.Sum(m => m.Balance);
            UnifyContext.Fill(new
            {
                Balance = amount,
            });

            var search2 = from a in search
                          join b in _departmentRepository.AsQueryable() on a.DepartmentId equals b.Id
                          select DtoHelper.TransCustomerDto(a, b);
            return search2.ToPagedList(input.page, input.size);

        }
        /// <summary>
        /// 保存客户
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [SecurityDefine("customer")]
        [UnitOfWork]
        public void SaveCustomer(CustomerDto input)
        {
            var oldCount = _customerRepository.Where(m => m.MedicalCardNo.Equals(input.MedicalCardNo) && m.Id != input.Id).Count();
            if (oldCount > 0)
            {
                throw Oops.Bah("医保号已存在，请检查").StatusCode(ErrorStatus.ValidationFaild);
            }
            if (input.Id > 0)
            {
                var customer = input.Adapt<cts_Customer>();
                _customerRepository.UpdateExclude(customer, new string[] { nameof(input.Balance) });
            }
            else
            {
                input.Id = YitIdHelper.NextId();
                var customer = input.Adapt<cts_Customer>();
                _customerRepository.Insert(customer);

                if (input.Balance != 0)
                {
                    _customerpaylogRepository.Insert(new cts_CustomerPayLog
                    {
                        CustomerId = input.Id,
                        CustomerName = input.Name,
                        ChangeAmount = input.Balance,
                        NewAmount = input.Balance,
                        OrderDate = DateTime.Now.Date,
                        Remark = "期初账目"
                    });
                }
            }

        }

        /// <summary>
        /// 获取 
        /// </summary>  
        public cts_Customer GetCustomer(long id)
        {
            return _customerRepository.FindOrDefault(id);
        }
        /// <summary>
        /// 删除 
        /// </summary>  
        [SecurityDefine("customer")]
        public void DeleteCustomer(long id)
        {
            if (_saleorderRepository.Where(s => s.CustomerId == id && !s.IsDeleted).Count() > 0)
            {
                throw Oops.Bah("该人员存在处方单，请误删除人员！").StatusCode(ErrorStatus.ValidationFaild);
            }
            _customerRepository.FakeDelete(id);
        }

        /// <summary>
        /// 客户账目明细
        /// </summary> 
        public PagedList<cts_CustomerPayLog> SearchCustomerPayLog(BaseInput input)
        {
            var search = _customerpaylogRepository.Where(m => m.CustomerId == input.customerid);
            if (input.sdate != null)
            {
                search = search.Where(m => m.CreatedTime >= input.sdate);
            }
            if (input.edate != null)
            {
                var edate = input.edate?.AddDays(1).Date;
                search = search.Where(m => m.CreatedTime < edate);
            }
            return search.OrderByDescending(m => m.OrderDate).ThenByDescending(m => m.Id).ToPagedList(input.page, input.size);
        }
        /// <summary>
        /// 新增一条账目明细
        /// </summary> 
        [SecurityDefine("customer")]
        [UnitOfWork]
        public void AddCustomerPayLog(cts_CustomerPayLog input)
        {
            var customer = _customerRepository.FindOrDefault(input.CustomerId);
            var changeAmount = input.ChangeAmount + input.DiscountAmount;
            input.OldAmount = customer.Balance;
            input.NewAmount = customer.Balance + changeAmount;
            customer.Balance += changeAmount;
            _customerpaylogRepository.Insert(input);
        }
        #endregion



    }
}
